#include "XNCtrl.h"
#include <stdio.h>
#include <cstdlib>
#include "global.h"

XNCtrl::XNCtrl(void)
{
	m_bQuit = false;
	m_bPause = false;
	m_bCalibrated = false;
}


XNCtrl::~XNCtrl(void)
{
}

void XNCtrl::NewUser(xn::UserGenerator& generator, XnUserID user, void* pCookie)
{
	m_nPlayer = user;
}

void XNCtrl::setPlayer( int &player )
{
	XnUserID aUsers[15];
	XnUInt16 nUsers = 15;
	m_UserGenerator.GetUsers(aUsers, nUsers);
	player = nUsers;
}

int XNCtrl::Init()
{
	XnStatus rc = XN_STATUS_OK;
	xn::EnumerationErrors errors;

	// init from file
	rc = m_Context.InitFromXmlFile(SAMPLE_XML_PATH);
	CHECK_ERRORS(rc, errors, "InitFromXmlFile");
	CHECK_RC(rc, "InitFromXml");

	// init nodes
	rc = m_Context.FindExistingNode(XN_NODE_TYPE_DEPTH, m_DepthGenerator);
	CHECK_RC(rc, "Find depth generator");
	rc = m_Context.FindExistingNode(XN_NODE_TYPE_USER, m_UserGenerator);
	CHECK_RC(rc, "Find user generator");
	rc = m_Context.FindExistingNode(XN_NODE_TYPE_IMAGE, m_ImageGenerator);
	CHECK_RC(rc, "Find image generator");
	m_DepthGenerator.GetAlternativeViewPointCap().SetViewPoint(m_ImageGenerator);

	// TODO skeleton or pose support may not be needed
	if (!m_UserGenerator.IsCapabilitySupported(XN_CAPABILITY_SKELETON) ||
		!m_UserGenerator.IsCapabilitySupported(XN_CAPABILITY_POSE_DETECTION)){
		printf("User generator doesn't support either skeleton or pose detection.\n");
		return XN_STATUS_ERROR;
	}
	m_UserGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_ALL);

	// start generating
	rc = m_Context.StartGeneratingAll();
	CHECK_RC(rc, "StartGenerating");

	// register handlers
	XnCallbackHandle hUserCBs;
	m_UserGenerator.RegisterUserCallbacks(CB_NewUser, CB_LostUser, NULL, hUserCBs);
	// TODO I don't think I need that
// 	m_sceneImg->m_UserGenerator.GetSkeletonCap().RegisterCalibrationCallbacks(CalibrationStarted, CalibrationEnded, NULL, hCalibrationCBs);
// 	m_sceneImg->m_UserGenerator.GetPoseDetectionCap().RegisterToPoseCallbacks(PoseDetected, NULL, NULL, hPoseCBs);
}

void XNCtrl::getMetaData( xn::SceneMetaData& sceneMD )
{
	m_UserGenerator.GetUserPixels(0, sceneMD);
}

void XNCtrl::getMetaData( xn::DepthMetaData& depthMD )
{
	m_DepthGenerator.GetMetaData(depthMD);
}

void XNCtrl::getMetaData( xn::ImageMetaData& imageMD )
{
	m_ImageGenerator.GetMetaData(imageMD);
}

void XNCtrl::CleanupExit()
{
	m_Context.Shutdown();
	exit (1);
}

void XNCtrl::IdleClean()
{
	if (m_bQuit) {
		CleanupExit();
	}
}

void XNCtrl::ReadNextData()
{
	if (!m_bPause)
		// Read next available data
		// Waits for any one specific node to have generated new data. This method then 'updates' each and every node in the entire production graph.
		m_Context.WaitOneUpdateAll(m_DepthGenerator);
}

void XNCtrl::DrawPlayerNote( int player )
{
	XnUserID aUsers[15];
	XnUInt16 nUsers = 15;
	m_UserGenerator.GetUsers(aUsers, nUsers);
	m_nPlayer = nUsers;
	for (int i = 0; i < nUsers; ++i){
		XnPoint3D com;
		m_UserGenerator.GetCoM(aUsers[i], com);
		m_DepthGenerator.ConvertRealWorldToProjective(1, &com, &com);
	}
}

void XNCtrl::getHFov( double &hfov,double &vfov )
{
	XnFieldOfView fov;
	m_DepthGenerator.GetFieldOfView(fov);
	hfov = fov.fHFOV;
	vfov = fov.fVFOV;
}

int XNCtrl::InitFromCode()
{
	XnStatus nRetVal = XN_STATUS_OK;

	// Initialize context object
	nRetVal = m_Context.Init();
	CHECK_RC(nRetVal, "InitFromXml");

	// Create a m_UserGenerator node
	nRetVal = m_UserGenerator.Create(m_Context);
	CHECK_RC(nRetVal, "create user generator");
	
	// Create a m_ImageGenerator node
	nRetVal = m_ImageGenerator.Create(m_Context);
	CHECK_RC(nRetVal, "create image generator");
	
	// Create a DepthGenerator node
	nRetVal = m_DepthGenerator.Create(m_Context);
	CHECK_RC(nRetVal, "create depth generator");


	// Set it to VGA maps at 30 FPS
	XnMapOutputMode mapMode;
	mapMode.nXRes = XN_VGA_X_RES;
	mapMode.nYRes = XN_VGA_Y_RES;
	mapMode.nFPS = 30;
	nRetVal = m_DepthGenerator.SetMapOutputMode(mapMode);
	CHECK_RC(nRetVal, "depth SetMapOutputMode");
	nRetVal = m_ImageGenerator.SetMapOutputMode(mapMode);
	CHECK_RC(nRetVal, "image SetMapOutputMode");	

	// Make it start generating data
	nRetVal = m_Context.StartGeneratingAll();
	CHECK_RC(nRetVal, "InitFromXml");

	return nRetVal;
}
